﻿Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Collections.Specialized
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.ComponentModel.Design.Serialization
Imports System.Diagnostics
Imports System.Globalization
Imports System.Runtime.CompilerServices
Imports System.Threading
Imports System.Workflow.ComponentModel
Imports System.Workflow.ComponentModel.Design
Imports System.Workflow.ComponentModel.Serialization

Namespace System.Workflow.Runtime
    <DesignerSerializer(GetType(DependencyObjectCodeDomSerializer), GetType(CodeDomSerializer))> _
    Public NotInheritable Class CorrelationToken
        Inherits DependencyObject
        Implements IPropertyValueProvider
        ' Methods
        Public Sub New()
        End Sub

        Public Sub New(ByVal name As String)
            Me.Name = name
        End Sub

        Private Shared Function GetEnclosingCompositeActivities(ByVal startActivity As Activity) As IEnumerable
            Return New <GetEnclosingCompositeActivities>d__0(-2) { _
                .<>3__startActivity = startActivity _
            }
        End Function

        Public Sub Initialize(ByVal activity As Activity, ByVal propertyValues As ICollection(Of CorrelationProperty))
            If Me.Initialized Then
                Throw New InvalidOperationException(String.Format(CultureInfo.CurrentCulture, ExecutionStringManager.CorrelationAlreadyInitialized, New Object() { Me.Name }))
            End If
            MyBase.SetValue(CorrelationToken.PropertiesProperty, propertyValues)
            Dim e As New CorrelationTokenEventArgs(Me, True)
            Dim list As IList(Of ActivityExecutorDelegateInfo(Of CorrelationTokenEventArgs)) = TryCast(MyBase.GetValue(CorrelationToken.SubscriptionsProperty),IList(Of ActivityExecutorDelegateInfo(Of CorrelationTokenEventArgs)))
            If (Not list Is Nothing) Then
                Dim info As ActivityExecutorDelegateInfo(Of CorrelationTokenEventArgs)
                For Each info In list
                    info.InvokeDelegate(ContextActivityUtils.ContextActivity(activity), e, True, False)
                Next
            End If
            MyBase.SetValue(CorrelationToken.InitializedProperty, True)
            WorkflowTrace.Runtime.TraceEvent(TraceEventType.Information, 0, "CorrelationToken initialized for {0} owner activity {1} ", New Object() { Me.Name, Me.OwnerActivityName })
        End Sub

        Public Sub SubscribeForCorrelationTokenInitializedEvent(ByVal activity As Activity, ByVal dataChangeListener As IActivityEventListener(Of CorrelationTokenEventArgs))
            If (dataChangeListener Is Nothing) Then
                Throw New ArgumentNullException("dataChangeListener")
            End If
            If (activity Is Nothing) Then
                Throw New ArgumentNullException("activity")
            End If
            Dim item As New ActivityExecutorDelegateInfo(Of CorrelationTokenEventArgs)(dataChangeListener, ContextActivityUtils.ContextActivity(activity), True)
            Dim list As IList(Of ActivityExecutorDelegateInfo(Of CorrelationTokenEventArgs)) = TryCast(MyBase.GetValue(CorrelationToken.SubscriptionsProperty),IList(Of ActivityExecutorDelegateInfo(Of CorrelationTokenEventArgs)))
            If (list Is Nothing) Then
                list = New List(Of ActivityExecutorDelegateInfo(Of CorrelationTokenEventArgs))
                MyBase.SetValue(CorrelationToken.SubscriptionsProperty, list)
            End If
            list.Add(item)
        End Sub

        Private Function System.Workflow.ComponentModel.Design.IPropertyValueProvider.GetPropertyValues(ByVal context As ITypeDescriptorContext) As ICollection Implements IPropertyValueProvider.GetPropertyValues
            Dim strings As New StringCollection
            If String.Equals(context.PropertyDescriptor.Name, "OwnerActivityName", StringComparison.Ordinal) Then
                Dim service As ISelectionService = TryCast(context.GetService(GetType(ISelectionService)),ISelectionService)
                If (((service Is Nothing) OrElse (service.SelectionCount <> 1)) OrElse Not TypeOf service.PrimarySelection Is Activity) Then
                    Return strings
                End If
                Dim primarySelection As Activity = TryCast(service.PrimarySelection,Activity)
                Dim activity2 As Activity
                For Each activity2 In CorrelationToken.GetEnclosingCompositeActivities(primarySelection)
                    Dim qualifiedName As String = activity2.QualifiedName
                    If Not strings.Contains(qualifiedName) Then
                        strings.Add(qualifiedName)
                    End If
                Next
            End If
            Return strings
        End Function

        Friend Sub Uninitialize(ByVal activity As Activity)
            MyBase.SetValue(CorrelationToken.PropertiesProperty, Nothing)
            Dim e As New CorrelationTokenEventArgs(Me, False)
            Dim list As IList(Of ActivityExecutorDelegateInfo(Of CorrelationTokenEventArgs)) = TryCast(MyBase.GetValue(CorrelationToken.SubscriptionsProperty),IList(Of ActivityExecutorDelegateInfo(Of CorrelationTokenEventArgs)))
            If (Not list Is Nothing) Then
                Dim array As ActivityExecutorDelegateInfo(Of CorrelationTokenEventArgs)() = New ActivityExecutorDelegateInfo(Of CorrelationTokenEventArgs)(list.Count  - 1) {}
                list.CopyTo(array, 0)
                Dim info As ActivityExecutorDelegateInfo(Of CorrelationTokenEventArgs)
                For Each info In array
                    info.InvokeDelegate(ContextActivityUtils.ContextActivity(activity), e, True, False)
                Next
            End If
            WorkflowTrace.Runtime.TraceEvent(TraceEventType.Information, 0, "CorrelationToken Uninitialized for {0} owner activity {1}", New Object() { Me.Name, Me.OwnerActivityName })
        End Sub

        Public Sub UnsubscribeFromCorrelationTokenInitializedEvent(ByVal activity As Activity, ByVal dataChangeListener As IActivityEventListener(Of CorrelationTokenEventArgs))
            If (dataChangeListener Is Nothing) Then
                Throw New ArgumentNullException("dataChangeListener")
            End If
            If (activity Is Nothing) Then
                Throw New ArgumentNullException("activity")
            End If
            Dim item As New ActivityExecutorDelegateInfo(Of CorrelationTokenEventArgs)(dataChangeListener, ContextActivityUtils.ContextActivity(activity), True)
            Dim list As IList(Of ActivityExecutorDelegateInfo(Of CorrelationTokenEventArgs)) = TryCast(MyBase.GetValue(CorrelationToken.SubscriptionsProperty),IList(Of ActivityExecutorDelegateInfo(Of CorrelationTokenEventArgs)))
            If (Not list Is Nothing) Then
                list.Remove(item)
            End If
        End Sub


        ' Properties
        <Browsable(False), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
        Public ReadOnly Property Initialized As Boolean
            Get
                Return CBool(MyBase.GetValue(CorrelationToken.InitializedProperty))
            End Get
        End Property

        <Browsable(False)> _
        Public Property Name As String
            Get
                Return CStr(MyBase.GetValue(CorrelationToken.NameProperty))
            End Get
            Set(ByVal value As String)
                MyBase.SetValue(CorrelationToken.NameProperty, value)
            End Set
        End Property

        <TypeConverter(GetType(PropertyValueProviderTypeConverter))> _
        Public Property OwnerActivityName As String
            Get
                Return CStr(MyBase.GetValue(CorrelationToken.OwnerActivityNameProperty))
            End Get
            Set(ByVal value As String)
                MyBase.SetValue(CorrelationToken.OwnerActivityNameProperty, value)
            End Set
        End Property

        <Browsable(False), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
        Public ReadOnly Property Properties As ICollection(Of CorrelationProperty)
            Get
                Return TryCast(MyBase.GetValue(CorrelationToken.PropertiesProperty),ICollection(Of CorrelationProperty))
            End Get
        End Property


        ' Fields
        Friend Shared ReadOnly InitializedProperty As DependencyProperty = DependencyProperty.Register("Initialized", GetType(Boolean), GetType(CorrelationToken), New PropertyMetadata(False, New Attribute() { New BrowsableAttribute(False), New DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden) }))
        Friend Shared ReadOnly NameProperty As DependencyProperty = DependencyProperty.Register("Name", GetType(String), GetType(CorrelationToken), New PropertyMetadata(DependencyPropertyOptions.Metadata, New Attribute() { New BrowsableAttribute(False) }))
        Friend Shared ReadOnly OwnerActivityNameProperty As DependencyProperty = DependencyProperty.Register("OwnerActivityName", GetType(String), GetType(CorrelationToken), New PropertyMetadata(DependencyPropertyOptions.Metadata, New Attribute() { New TypeConverterAttribute(GetType(PropertyValueProviderTypeConverter)) }))
        Friend Shared ReadOnly PropertiesProperty As DependencyProperty = DependencyProperty.Register("Properties", GetType(ICollection(Of CorrelationProperty)), GetType(CorrelationToken), New PropertyMetadata(New Attribute() { New BrowsableAttribute(False), New DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden) }))
        Friend Shared ReadOnly SubscriptionsProperty As DependencyProperty = DependencyProperty.Register("Subscriptions", GetType(IList(Of ActivityExecutorDelegateInfo(Of CorrelationTokenEventArgs))), GetType(CorrelationToken))

        ' Nested Types
        <CompilerGenerated> _
        Private NotInheritable Class <GetEnclosingCompositeActivities>d__0
            Implements IEnumerable(Of Object), IEnumerable, IEnumerator(Of Object), IEnumerator, IDisposable
            ' Methods
            <DebuggerHidden> _
            Public Sub New(ByVal <>1__state As Integer)
                Me.<>1__state = <>1__state
                Me.<>l__initialThreadId = Thread.CurrentThread.ManagedThreadId
            End Sub

            Private Function MoveNext() As Boolean Implements IEnumerator.MoveNext
                Select Case Me.<>1__state
                    Case 0
                        Me.<>1__state = -1
                        Me.<currentActivity>5__1 = Nothing
                        Me.<activityStack>5__2 = New Stack(Of Activity)
                        Me.<activityStack>5__2.Push(Me.startActivity)
                        goto Label_00A1
                    Case 1
                        Me.<>1__state = -1
                        goto Label_008B
                    Case Else
                        goto Label_00B7
                End Select
            Label_008B:
                Me.<activityStack>5__2.Push(Me.<currentActivity>5__1.Parent)
            Label_00A1:
                If (Not Me.<currentActivity>5__1 = Me.<activityStack>5__2.Pop Is Nothing) Then
                    If (GetType(CompositeActivity).IsAssignableFrom(Me.<currentActivity>5__1.GetType) AndAlso Me.<currentActivity>5__1.Enabled) Then
                        Me.<>2__current = Me.<currentActivity>5__1
                        Me.<>1__state = 1
                        Return True
                    End If
                    goto Label_008B
                End If
            Label_00B7:
                Return False
            End Function

            <DebuggerHidden> _
            Private Function System.Collections.Generic.IEnumerable<System.Object>.GetEnumerator() As IEnumerator(Of Object) Implements IEnumerable(Of Object).GetEnumerator
                Dim d__ As <GetEnclosingCompositeActivities>d__0
                If ((Thread.CurrentThread.ManagedThreadId = Me.<>l__initialThreadId) AndAlso (Me.<>1__state = -2)) Then
                    Me.<>1__state = 0
                    d__ = Me
                Else
                    d__ = New <GetEnclosingCompositeActivities>d__0(0)
                End If
                d__.startActivity = Me.<>3__startActivity
                Return d__
            End Function

            <DebuggerHidden> _
            Private Function System.Collections.IEnumerable.GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
                Return Me.System.Collections.Generic.IEnumerable<System.Object>.GetEnumerator
            End Function

            <DebuggerHidden> _
            Private Sub System.Collections.IEnumerator.Reset() Implements IEnumerator.Reset
                Throw New NotSupportedException
            End Sub

            Private Sub System.IDisposable.Dispose() Implements IDisposable.Dispose
            End Sub


            ' Properties
            Private ReadOnly Property System.Collections.Generic.IEnumerator<System.Object>.Current As Object
                <DebuggerHidden> _
                Get
                    Return Me.<>2__current
                End Get
            End Property

            Private ReadOnly Property System.Collections.IEnumerator.Current As Object
                <DebuggerHidden> _
                Get
                    Return Me.<>2__current
                End Get
            End Property


            ' Fields
            Private <>1__state As Integer
            Private <>2__current As Object
            Public <>3__startActivity As Activity
            Private <>l__initialThreadId As Integer
            Public <activityStack>5__2 As Stack(Of Activity)
            Public <currentActivity>5__1 As Activity
            Public startActivity As Activity
        End Class
    End Class
End Namespace

